package com.fy.fyspace.service.hotness.strategy;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 热度计算策略工厂
 * 设计模式：工厂模式，用于创建和管理不同的热度计算策略
 * 作用：统一管理策略实例，提供策略的注册和获取功能
 * 
 * @author fwq
 * @since 2024-12-19
 */
@Slf4j
@Component
public class HotnessStrategyFactory {
    
    /**
     * 策略映射表
     */
    private final Map<String, HotnessCalculationStrategy> strategyMap = new ConcurrentHashMap<>();
    
    /**
     * 默认策略名称
     */
    private static final String DEFAULT_STRATEGY = "standardHotnessStrategy";
    
    /**
     * 构造函数，自动注入所有策略实现
     * 设计模式：依赖注入模式
     */
    @Autowired
    public HotnessStrategyFactory(List<HotnessCalculationStrategy> strategies) {
        for (HotnessCalculationStrategy strategy : strategies) {
            registerStrategy(strategy);
        }
        log.info("热度计算策略工厂初始化完成，注册策略数量: {}", strategies.size());
    }
    
    /**
     * 注册策略
     * 使用策略的类名作为键名
     * 
     * @param strategy 策略实例
     */
    public void registerStrategy(HotnessCalculationStrategy strategy) {
        // 获取策略的类名，转换为驼峰命名作为键
        String className = strategy.getClass().getSimpleName();
        String strategyName = convertToCamelCase(className);
        
        strategyMap.put(strategyName, strategy);
        log.info("注册热度计算策略: {} -> {}", strategyName, strategy.getStrategyName());
    }
    
    /**
     * 将类名转换为驼峰命名
     * 例如：StandardHotnessStrategy -> standardHotnessStrategy
     */
    private String convertToCamelCase(String className) {
        if (className == null || className.isEmpty()) {
            return className;
        }
        
        // 将首字母转为小写
        return className.substring(0, 1).toLowerCase() + className.substring(1);
    }
    
    /**
     * 获取策略
     * 
     * @param strategyName 策略名称
     * @return 策略实例
     */
    public HotnessCalculationStrategy getStrategy(String strategyName) {
        HotnessCalculationStrategy strategy = strategyMap.get(strategyName);
        if (strategy == null) {
            log.warn("未找到策略: {}，使用默认策略", strategyName);
            strategy = strategyMap.get(DEFAULT_STRATEGY);
        }
        return strategy;
    }
    
    /**
     * 获取默认策略
     * 
     * @return 默认策略实例
     */
    public HotnessCalculationStrategy getDefaultStrategy() {
        return getStrategy(DEFAULT_STRATEGY);
    }
    
    /**
     * 获取所有策略名称
     * 
     * @return 策略名称列表
     */
    public List<String> getAllStrategyNames() {
        return List.copyOf(strategyMap.keySet());
    }
    
    /**
     * 获取所有启用的策略名称
     * 
     * @return 启用的策略名称列表
     */
    public List<String> getEnabledStrategyNames() {
        return strategyMap.values().stream()
                .filter(HotnessCalculationStrategy::isEnabled)
                .map(strategy -> convertToCamelCase(strategy.getClass().getSimpleName()))
                .collect(Collectors.toList());
    }
    
    /**
     * 检查策略是否存在
     * 
     * @param strategyName 策略名称
     * @return 是否存在
     */
    public boolean hasStrategy(String strategyName) {
        return strategyMap.containsKey(strategyName);
    }
    
    /**
     * 获取策略信息
     * 
     * @param strategyName 策略名称
     * @return 策略信息
     */
    public StrategyInfo getStrategyInfo(String strategyName) {
        HotnessCalculationStrategy strategy = getStrategy(strategyName);
        if (strategy != null) {
            return new StrategyInfo(
                convertToCamelCase(strategy.getClass().getSimpleName()), // 使用驼峰命名的策略名称
                strategy.getStrategyDescription(),
                strategy.getStrategyType(),
                strategy.isEnabled()
            );
        }
        return null;
    }
    
    /**
     * 策略信息内部类
     */
    public static class StrategyInfo {
        private final String name;
        private final String description;
        private final String type;
        private final boolean enabled;
        
        public StrategyInfo(String name, String description, String type, boolean enabled) {
            this.name = name;
            this.description = description;
            this.type = type;
            this.enabled = enabled;
        }
        
        public String getName() { return name; }
        public String getDescription() { return description; }
        public String getType() { return type; }
        public boolean isEnabled() { return enabled; }
    }
} 